#include "Vector3.h"
#include <math.h>

const Vector3f Vector3f::zero = Vector3f(0.0f,0.0f,0.0f);
const Vector3f Vector3f::x_axis = Vector3f(1.0f,0.0f,0.0f);
const Vector3f Vector3f::y_axis = Vector3f(0.0f,1.0f,0.0f);
const Vector3f Vector3f::z_axis = Vector3f(0.0f,0.0f,1.0f);

Vector3f::Vector3f(void){
	x=y=z=0.0f;
}

Vector3f::Vector3f(float a, float b, float c){
	x = a;
	y = b;
	z = c;
}

Vector3f::Vector3f(const Vector3f &other){
	x=other.x;
	y=other.y;
	z=other.z;
}

Vector3f::~Vector3f(void){

}

Vector3f& Vector3f::operator+=(const Vector3f &other)
{
	x+=other.x;
	y+=other.y;
	z+=other.z;
	return *this;
}

Vector3f Vector3f::operator+(const Vector3f &other) const
{
	Vector3f result(x,y,z);
	result += other;
	return result;
}

Vector3f& Vector3f::operator-=(const Vector3f &other)
{
	x-=other.x;
	y-=other.y;
	z-=other.z;
	return *this;
}

Vector3f Vector3f::operator-(const Vector3f &other) const
{
	Vector3f result(x,y,z);
	result -= other;
	return result;
}

Vector3f& Vector3f::operator*=(const float &other)
{
	x*=other;
	y*=other;
	z*=other;
	return *this;
}

Vector3f Vector3f::operator*(const float &other) const
{
	Vector3f result(x,y,z);
	result *= other;
	return result;
}

Vector3f Vector3f::cross(const Vector3f &other) const
{
	Vector3f result;

	result.x=y*other.z - z*other.y;
	result.y=z*other.x - x*other.z;
	result.z=x*other.y - y*other.x;

	return result;
}

float Vector3f::dot(const Vector3f &other) const
{
	return x*other.x + y*other.y + z*other.z;
}

void Vector3f::normalize()
{
	float l = length();
	x /= l;
	y = (float) ( (double)y / (double) l);
	z /= l;
}

Vector3f Vector3f::normalize(const Vector3f& v)
{
	Vector3f n = v;
	n.normalize();
	return n;
}

float Vector3f::length() const
{
	return sqrt(x*x + y*y + z*z);
}


float Vector3f::cosA(const Vector3f& other ) const
{
	float num = dot(other); 
	float den = length()*other.length();
	return num/den;
}

float Vector3f::angle(const Vector3f& other ) const
{
	return acos( cosA(other) ); //probably uses a lot of processing time
}


Vector3f& Vector3f::rotate(const Vector3f& a, float radians) {
	
	Vector3f tmp = Vector3f();

	float s = sin(radians);
	float c = cos(radians);

	tmp.x = (float) (x*(a.x*a.x*(1-c)+c)     + y*(a.x*a.y*(1-c)-a.z*s) + z*(a.x*a.z*(1-c)+a.y*s));
	tmp.y = (float) (x*(a.y*a.x*(1-c)+a.z*s) + y*(a.y*a.y*(1-c)+c)     + z*(a.y*a.z*(1-c)-a.x*s));
	tmp.z = (float) (x*(a.x*a.z*(1-c)-a.y*s) + y*(a.y*a.z*(1-c)+a.x*s) + z*(a.z*a.z*(1-c)+c));
	*this = tmp;
	return *this;
}